import pandas as pd
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import re
import uuid

# 修改GUI界面
# 在这里设置固定的列名
FIXED_COLUMN_NAME = "数据项"  # 修改为您需要处理的列名
WHOLE_INDICATORS = ["村、社区", "龄、学历、学","个数、年收烘蚕茧（吨）、烘茧设备（套、台）",
                    "大社区、公共服务中心", "县（市、区、开发区）", "物业费收支、公共收益",
                    "因工作不力、违纪违法","春、夏、早秋、中秋、晚秋","县、市、省、国家"]  # 整体标志


def split_string(s, whole_list, split_chars=None):
    """
    分割字符串，处理括号嵌套情况

    参数:
    s: 要处理的字符串
    whole_list: 应视为整体的字符串列表

    返回:
    分割后的字符串列表和对应的序号
    """
    if not s or pd.isna(s):
        return [(s, 1)]

    # 如果整个字符串在整体列表中，直接返回
    if s in whole_list:
        return [(s, 1)]

    # 第一步：保护整体字符串中的顿号
    protected_s, mapping = protect_whole_strings(s, whole_list)

    # 第二步：按照最外层的顿号分割（不在任何括号内的顿号）
    # segments = split_outer_commas(protected_s)
    segments = split_outer_commas(protected_s, split_chars)

    # 第三步：处理每个分段
    result = []
    for segment in segments:
        # 恢复被保护的顿号
        restored_segment = restore_protected_commas(segment, mapping)

        # 检查是否有括号
        if has_brackets(restored_segment) and ('、' in restored_segment or '。' in restored_segment):
            # 处理有括号的情况
            # bracket_results = process_brackets(restored_segment, whole_list)  注释
            # result.extend(bracket_results)    注释
            result.append(restored_segment.strip())
        else:
            # 没有括号的直接添加
            result.append(restored_segment.strip())

    # 恢复所有被保护的顿号
    result = [restore_protected_commas(item, mapping) for item in result]

    # 为每个分割结果分配序号
    numbered_result = [(item, i + 1) for i, item in enumerate(result)]

    return numbered_result


def has_brackets(s):
    """检查字符串中是否有括号"""
    brackets = ['(', ')', '（', '）', '[', ']', '【', '】', '{', '}', '｛', '｝']
    return any(bracket in s for bracket in brackets)


def protect_whole_strings(s, whole_list):
    """
    保护整体字符串中的顿号，将其替换为特殊字符

    参数:
    s: 要处理的字符串
    whole_list: 应视为整体的字符串列表

    返回:
    处理后的字符串和映射关系
    """
    if not whole_list:
        return s, {}

    # 创建一个映射表，用于记录被替换的顿号和对应的特殊字符
    mapping = {}
    protected_s = s

    # 对整体列表按长度降序排序，先处理长的字符串
    sorted_whole_list = sorted(whole_list, key=len, reverse=True)

    for i, whole_str in enumerate(sorted_whole_list):
        if ('、' in whole_str or '。' in whole_str ) and whole_str in protected_s:
            # 使用UUID生成唯一标识符，避免冲突
            special_char = f"__PLACEHOLDER_{uuid.uuid4().hex[:8]}__"
            # 替换整体字符串中的顿号
            protected_whole_str = whole_str.replace('、', special_char)
            # 替换原始字符串中的整体字符串
            protected_s = protected_s.replace(whole_str, protected_whole_str)
            # 记录映射关系
            mapping[special_char] = '、'

    return protected_s, mapping


def restore_protected_commas(s, mapping):
    """
    恢复被保护的特殊字符为顿号

    参数:
    s: 要处理的字符串
    mapping: 特殊字符到顿号的映射

    返回:
    恢复后的字符串
    """
    restored_s = s
    for special_char, comma in mapping.items():
        restored_s = restored_s.replace(special_char, comma)
    return restored_s


def split_outer_commas(s, split_chars=None):
    """
    按照最外层的指定符号分割字符串（不在任何括号内的指定符号）

    参数:
    s: 要分割的字符串
    split_chars: 分割符号列表，默认为['、', '。']
    """
    if split_chars is None:
        split_chars = ['、', '。']

    segments = []
    current = []
    bracket_depth = 0
    parentheses_depth = 0
    brace_depth = 0

    for char in s:
        # 修改这里：支持多个分割符号
        if (char in split_chars) and bracket_depth == 0 and parentheses_depth == 0 and brace_depth == 0:
            segments.append(''.join(current))
            current = []
        else:
            current.append(char)
            if char == '[' or char == '【':
                bracket_depth += 1
            elif char == ']' or char == '】':
                bracket_depth -= 1
            elif char == '(' or char == '（':
                parentheses_depth += 1
            elif char == ')' or char == '）':
                parentheses_depth -= 1
            elif char == '{' or char == '｛':
                brace_depth += 1
            elif char == '}' or char == '｝':
                brace_depth -= 1

    if current:
        segments.append(''.join(current))

    return segments


def find_matching_bracket(s, start_idx, bracket_type):
    """
    找到与起始括号匹配的结束括号位置

    参数:
    s: 字符串
    start_idx: 起始括号的位置
    bracket_type: 括号类型 ('parentheses', 'bracket', 'brace')

    返回:
    匹配的结束括号位置，如果没有找到则返回-1
    """
    if bracket_type == 'parentheses':
        open_char = ['(', '（']
        close_char = [')', '）']
    elif bracket_type == 'bracket':
        open_char = ['[', '【']
        close_char = [']', '】']
    else:  # brace
        open_char = ['{', '｛']
        close_char = ['}', '｝']

    depth = 1
    for i in range(start_idx + 1, len(s)):
        if s[i] in open_char:
            depth += 1
        elif s[i] in close_char:
            depth -= 1
            if depth == 0:
                return i

    return -1  # 没有找到匹配的结束括号


def process_brackets(s, whole_list, split_chars=None):
    """
    处理包含括号的字符串
    """
    # 找到最外层括号的位置
    bracket_start = -1
    bracket_type = None

    for i, char in enumerate(s):
        if char in ['(', '（']:
            bracket_start = i
            bracket_type = 'parentheses'
            break
        elif char in ['[', '【']:
            bracket_start = i
            bracket_type = 'bracket'
            break
        elif char in ['{', '｛']:
            bracket_start = i
            bracket_type = 'brace'
            break

    if bracket_start == -1:
        return [s.strip()]

    # 找到匹配的括号结束位置
    bracket_end = find_matching_bracket(s, bracket_start, bracket_type)

    if bracket_end == -1:
        # 没有找到匹配的结束括号，将整个字符串视为一个整体
        return [s.strip()]

    # 提取括号前、括号内容和括号后的部分
    prefix = s[:bracket_start].strip()
    bracket_content = s[bracket_start + 1:bracket_end].strip()
    suffix = s[bracket_end + 1:].strip()

    # 检查括号内容是否在整体列表中
    if bracket_content in whole_list:
        # 作为整体处理
        result_item = f"{prefix}_{bracket_content}"
        if suffix:
            result_item += f"_{suffix}"
        return [result_item]
    else:
        # 递归处理括号内容
        # sub_items = [item for item, _ in split_string(bracket_content, whole_list)]
        sub_items = [item for item, _ in split_string(bracket_content, whole_list, split_chars)]
        result = []
        for item in sub_items:
            result_item = f"{prefix}_{item}"
            if suffix:
                result_item += f"_{suffix}"
            result.append(result_item)
        return result


def process_excel_file(file_path, sheet_name, whole_list, split_chars=None):
    """
    处理Excel文件

    参数:
    file_path: Excel文件路径
    sheet_name: 要处理的工作表名称
    whole_list: 应视为整体的字符串列表

    返回:
    处理后的DataFrame和原始DataFrame
    """
    # 读取Excel文件
    df = pd.read_excel(file_path, sheet_name=sheet_name)

    # 检查固定列是否存在
    if FIXED_COLUMN_NAME not in df.columns:
        raise ValueError(f"固定列 '{FIXED_COLUMN_NAME}' 在工作表 '{sheet_name}' 中不存在")

    # 创建新DataFrame存储处理后的数据
    new_rows = []

    # 处理每一行数据
    for index, row in df.iterrows():
        original_value = row[FIXED_COLUMN_NAME]
        # split_values = split_string(original_value, whole_list)
        split_values = split_string(original_value, whole_list, split_chars)

        # 为每个分割后的值创建新行
        for value, seq_num in split_values:
            new_row = row.copy()
            new_row[FIXED_COLUMN_NAME] = value
            new_row['分割序号'] = seq_num  # 添加分割序号
            new_rows.append(new_row)

    # 创建新的DataFrame
    new_df = pd.DataFrame(new_rows)

    return new_df, df


class ExcelProcessorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Excel数据处理器")
        self.root.geometry("600x400")

        self.file_path = None
        self.sheet_name = None
        self.whole_list = []

        self.use_period_split = tk.BooleanVar(value=False)  # 默认不启用句号分割 新加
        self.custom_split_chars = tk.StringVar(value="、")  # 默认分割符号为顿号 新加
        self.create_widgets()

    def create_widgets(self):
        # 文件选择部分
        file_frame = tk.Frame(self.root)
        file_frame.pack(pady=10)


        tk.Label(file_frame, text="选择Excel文件:").grid(row=0, column=0, padx=5, pady=5)
        self.file_path_label = tk.Label(file_frame, text="未选择文件", width=50, relief="sunken")
        self.file_path_label.grid(row=0, column=1, padx=5, pady=5)
        tk.Button(file_frame, text="浏览", command=self.browse_file).grid(row=0, column=2, padx=5, pady=5)

        # Sheet选择部分
        sheet_frame = tk.Frame(self.root)
        sheet_frame.pack(pady=10)

        tk.Label(sheet_frame, text="选择Sheet:").grid(row=0, column=0, padx=5, pady=5)
        self.sheet_combo = ttk.Combobox(sheet_frame, state="readonly", width=30)
        self.sheet_combo.grid(row=0, column=1, padx=5, pady=5)

        # 显示固定列名
        column_frame = tk.Frame(self.root)
        column_frame.pack(pady=10)

        tk.Label(column_frame, text="处理列:").grid(row=0, column=0, padx=5, pady=5)
        tk.Label(column_frame, text=FIXED_COLUMN_NAME, relief="sunken", width=30).grid(row=0, column=1, padx=5, pady=5)

        # 整体列表部分
        whole_list_frame = tk.Frame(self.root)
        whole_list_frame.pack(pady=10)

        tk.Label(whole_list_frame, text="整体字符串列表(用逗号分隔):").grid(row=0, column=0, padx=5, pady=5)
        self.whole_list_entry = tk.Entry(whole_list_frame, width=50)
        self.whole_list_entry.grid(row=0, column=1, padx=5, pady=5)
        self.whole_list_entry.insert(0, ",".join(WHOLE_INDICATORS))

        # 分割选项部分
        split_options_frame = tk.Frame(self.root)
        split_options_frame.pack(pady=10)
        tk.Label(split_options_frame, text="分割选项:").grid(row=0, column=0, padx=5, pady=5, sticky="w")

        # 句号分割复选框
        self.period_check = tk.Checkbutton(split_options_frame, text="启用句号分割",
                                           variable=self.use_period_split)
        self.period_check.grid(row=0, column=1, padx=5, pady=5, sticky="w")

        # 自定义分割符号输入框
        tk.Label(split_options_frame, text="自定义分割符号:").grid(row=1, column=0, padx=5, pady=5, sticky="w")
        self.custom_split_entry = tk.Entry(split_options_frame, textvariable=self.custom_split_chars, width=10)
        self.custom_split_entry.grid(row=1, column=1, padx=5, pady=5, sticky="w")

        # 预览按钮
        preview_frame = tk.Frame(self.root)
        preview_frame.pack(pady=5)

        tk.Button(preview_frame, text="预览分割效果", command=self.preview_split).pack(padx=10)

        # 处理按钮
        button_frame = tk.Frame(self.root)
        button_frame.pack(pady=10)

        tk.Button(button_frame, text="处理数据", command=self.process_data).pack(side=tk.LEFT, padx=10)
        tk.Button(button_frame, text="保存结果", command=self.save_result).pack(side=tk.LEFT, padx=10)

        # 状态栏
        self.status_label = tk.Label(self.root, text="就绪", relief="sunken", anchor="w")
        self.status_label.pack(side=tk.BOTTOM, fill=tk.X)

        # 进度条
        self.progress = ttk.Progressbar(self.root, orient=tk.HORIZONTAL, length=100, mode='indeterminate')
        self.progress.pack(side=tk.BOTTOM, fill=tk.X)

        self.processed_df = None
        self.original_df = None

    def browse_file(self):
        file_path = filedialog.askopenfilename(
            title="选择Excel文件",
            filetypes=[("Excel files", "*.xlsx *.xls")]
        )
        if file_path:
            self.file_path = file_path
            self.file_path_label.config(text=file_path)
            self.load_sheet_names()

    def load_sheet_names(self):
        try:
            excel_file = pd.ExcelFile(self.file_path)
            sheet_names = excel_file.sheet_names
            self.sheet_combo["values"] = sheet_names
            if sheet_names:
                self.sheet_combo.current(0)
            self.status_label.config(text="成功加载文件")
        except Exception as e:
            messagebox.showerror("错误", f"加载文件时出错: {str(e)}")
            self.status_label.config(text="加载文件失败")

    def preview_split(self):
        if not all([self.file_path, self.sheet_combo.get()]):
            messagebox.showerror("错误", "请先选择文件和工作表")
            return

        try:
            # 获取整体列表
            whole_list_str = self.whole_list_entry.get()
            self.whole_list = [item.strip() for item in whole_list_str.split(",") if item.strip()]

            # 读取前5行进行预览
            df = pd.read_excel(self.file_path, sheet_name=self.sheet_combo.get(), nrows=5)

            if FIXED_COLUMN_NAME not in df.columns:
                messagebox.showerror("错误", f"列 '{FIXED_COLUMN_NAME}' 不存在")
                return

            preview_text = "预览分割效果:\n\n"
            for i, value in enumerate(df[FIXED_COLUMN_NAME].head(3)):
                if pd.isna(value):
                    continue

                split_values = split_string(value, self.whole_list)
                preview_text += f"原始: {value}\n"
                preview_text += f"分割后: {[f'{v} (序号:{n})' for v, n in split_values]}\n\n"

            messagebox.showinfo("预览", preview_text)

        except Exception as e:
            messagebox.showerror("错误", f"预览时出错: {str(e)}")

    def process_data(self):
        if not all([self.file_path, self.sheet_combo.get()]):
            messagebox.showerror("错误", "请先选择文件和工作表")
            return

        try:
            # 获取整体列表
            whole_list_str = self.whole_list_entry.get()
            self.whole_list = [item.strip() for item in whole_list_str.split(",") if item.strip()]

            # 获取分割符号
            split_chars = list(self.custom_split_chars.get())
            if self.use_period_split.get() and '。' not in split_chars:
                split_chars.append('。')

            # 处理数据
            self.status_label.config(text="正在处理数据...")
            self.progress.start()
            self.root.update()

            self.processed_df, self.original_df = process_excel_file(
                self.file_path,
                self.sheet_combo.get(),
                self.whole_list,
                split_chars
            )

            self.progress.stop()
            self.status_label.config(
                text=f"处理完成! 原始行数: {len(self.original_df)}, 处理后行数: {len(self.processed_df)}")
            messagebox.showinfo("完成",
                                f"处理完成! 原始行数: {len(self.original_df)}, 处理后行数: {len(self.processed_df)}")

        except Exception as e:
            self.progress.stop()
            messagebox.showerror("错误", f"处理数据时出错: {str(e)}")
            self.status_label.config(text="处理数据失败")

    def save_result(self):
        if self.processed_df is None:
            messagebox.showerror("错误", "请先处理数据")
            return

        try:
            save_path = filedialog.asksaveasfilename(
                title="保存结果",
                defaultextension=".xlsx",
                filetypes=[("Excel files", "*.xlsx")]
            )

            if save_path:
                self.status_label.config(text="正在保存结果...")
                self.progress.start()
                self.root.update()

                # 使用ExcelWriter创建包含多个工作表的工作簿
                with pd.ExcelWriter(save_path) as writer:
                    self.processed_df.to_excel(writer, sheet_name="分割后数据", index=False)
                    self.original_df.to_excel(writer, sheet_name="原始数据", index=False)

                self.progress.stop()
                self.status_label.config(text=f"结果已保存到: {save_path}")
                messagebox.showinfo("成功", f"结果已保存到: {save_path}")

        except Exception as e:
            self.progress.stop()
            messagebox.showerror("错误", f"保存结果时出错: {str(e)}")
            self.status_label.config(text="保存结果失败")


if __name__ == "__main__":
    root = tk.Tk()
    app = ExcelProcessorApp(root)
    root.mainloop()